import * as XLSX from 'xlsx'
import jsPDF from 'jspdf'
import html2canvas from 'html2canvas'
import { AuditLogRecord } from '../api'

/**
 * 导出审计日志为 Excel
 */
export async function exportAuditLogsToExcel(
  logs: AuditLogRecord[],
  filename: string = `audit-logs-${new Date().toISOString().slice(0, 10)}.xlsx`
) {
  // 准备数据
  const data = logs.map((log) => ({
    时间: log.operationTime || log.createdAt || '',
    IP地址: log.ipAddress || '未知',
    操作人: log.operatorName || log.operatorAccount || '匿名用户',
    角色: log.operatorRole || '未知',
    模块: log.module || '通用模块',
    操作类型: getOperationTypeLabel(log.operationType),
    操作对象: log.targetName || '--',
    对象类型: log.targetType || '未指定对象',
    操作结果: log.resultStatus === 'success' ? '成功' : '失败',
    结果消息: log.resultMessage || '',
    风险等级: getRiskLevelLabel(log.riskLevel),
    风险原因: log.riskReason || '',
    状态: `${log.isRead ? '已读' : '未读'} / ${log.isAbnormal ? '异常' : '正常'}`,
    关联ID: log.correlationId || '',
    链路ID: log.chainId || '',
    标签: log.tags?.join('、') || '',
  }))

  // 创建工作簿
  const wb = XLSX.utils.book_new()

  // 创建工作表
  const ws = XLSX.utils.json_to_sheet(data)

  // 设置列宽
  const colWidths = [
    { wch: 20 }, // 时间
    { wch: 15 }, // IP地址
    { wch: 15 }, // 操作人
    { wch: 12 }, // 角色
    { wch: 15 }, // 模块
    { wch: 12 }, // 操作类型
    { wch: 20 }, // 操作对象
    { wch: 15 }, // 对象类型
    { wch: 10 }, // 操作结果
    { wch: 20 }, // 结果消息
    { wch: 10 }, // 风险等级
    { wch: 20 }, // 风险原因
    { wch: 15 }, // 状态
    { wch: 20 }, // 关联ID
    { wch: 20 }, // 链路ID
    { wch: 20 }, // 标签
  ]
  ws['!cols'] = colWidths

  // 添加工作表到工作簿
  XLSX.utils.book_append_sheet(wb, ws, '审计日志')

  // 导出文件
  XLSX.writeFile(wb, filename)
}

/**
 * 导出审计日志为 PDF（使用 iframe + html2canvas，确保中文字体正确加载）
 */
export async function exportAuditLogsToPDF(
  logs: AuditLogRecord[],
  filename: string = `audit-logs-${new Date().toISOString().slice(0, 10)}.pdf`
) {
  // 创建临时 HTML 表格
  const tableHtml = createTableHTML(logs)
  
  // 创建 iframe 来渲染 HTML（确保字体正确加载）
  const iframe = document.createElement('iframe')
  iframe.style.position = 'fixed'
  iframe.style.left = '0'
  iframe.style.top = '0'
  iframe.style.width = '1200px'
  iframe.style.height = '800px'
  iframe.style.border = 'none'
  iframe.style.zIndex = '9999'
  document.body.appendChild(iframe)

  return new Promise<void>((resolve, reject) => {
    iframe.onload = async () => {
      try {
        const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document
        if (!iframeDoc) {
          throw new Error('无法访问 iframe 文档')
        }

        // 写入 HTML 内容
        iframeDoc.open()
        iframeDoc.write(tableHtml)
        iframeDoc.close()

        // 等待内容渲染和字体加载
        await new Promise(resolve => setTimeout(resolve, 1000))

        // 获取 iframe 中的 body 元素
        const body = iframeDoc.body
        if (!body) {
          throw new Error('无法获取 iframe body')
        }

        // 使用 html2canvas 将表格转换为图片
        const canvas = await html2canvas(body, {
          scale: 2, // 提高清晰度
          useCORS: true,
          logging: false,
          backgroundColor: '#ffffff',
          allowTaint: true,
          windowWidth: 1200,
          windowHeight: body.scrollHeight,
        })

        // 计算图片尺寸
        const imgWidth = canvas.width
        const imgHeight = canvas.height
        const pdfWidth = 297 // A4 横向宽度（mm）
        const pdfHeight = 210 // A4 横向高度（mm）
        const ratio = Math.min(pdfWidth / (imgWidth * 0.264583), pdfHeight / (imgHeight * 0.264583))

        // 创建 PDF
        const pdf = new jsPDF('landscape', 'mm', 'a4')
        const pdfImgWidth = imgWidth * ratio * 0.264583
        const pdfImgHeight = imgHeight * ratio * 0.264583

        // 如果图片高度超过一页，需要分页
        if (pdfImgHeight <= pdfHeight) {
          // 单页可以容纳
          pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, pdfImgWidth, pdfImgHeight)
        } else {
          // 需要分页
          let heightLeft = pdfImgHeight
          let position = 0

          pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, pdfImgWidth, pdfImgHeight)
          heightLeft -= pdfHeight

          while (heightLeft > 0) {
            position = heightLeft - pdfImgHeight
            pdf.addPage()
            pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, pdfImgWidth, pdfImgHeight)
            heightLeft -= pdfHeight
          }
        }

        // 保存文件
        pdf.save(filename)
        resolve()
      } catch (error) {
        console.error('PDF导出失败:', error)
        reject(error)
      } finally {
        // 清理临时元素
        if (document.body.contains(iframe)) {
          document.body.removeChild(iframe)
        }
      }
    }

    // 设置 iframe src 为空，触发 onload
    iframe.src = 'about:blank'
  })
}

/**
 * 创建表格 HTML
 */
function createTableHTML(logs: AuditLogRecord[]): string {
  const headers = ['时间', 'IP地址', '操作人', '角色', '模块', '操作类型', '操作对象', '对象类型', '结果', '风险等级', '状态']
  
  let html = `
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
        body {
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
          margin: 0;
          padding: 20px;
          background: white;
          font-size: 12px;
        }
        .header {
          text-align: center;
          margin-bottom: 20px;
        }
        .title {
          font-size: 20px;
          font-weight: bold;
          margin-bottom: 10px;
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
        }
        .info {
          font-size: 12px;
          color: #666;
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
        }
        table {
          width: 100%;
          border-collapse: collapse;
          font-size: 11px;
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
        }
        th {
          background-color: #f5f5f5;
          border: 1px solid #ddd;
          padding: 8px;
          text-align: left;
          font-weight: bold;
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
        }
        td {
          border: 1px solid #ddd;
          padding: 6px;
          text-align: left;
          font-family: "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", Arial, sans-serif;
        }
        tr:nth-child(even) {
          background-color: #f9f9f9;
        }
      </style>
    </head>
    <body>
      <div class="header">
        <div class="title">审计日志导出</div>
        <div class="info">导出时间: ${new Date().toLocaleString('zh-CN')} | 总记录数: ${logs.length}</div>
      </div>
      <table>
        <thead>
          <tr>
            ${headers.map(h => `<th>${h}</th>`).join('')}
          </tr>
        </thead>
        <tbody>
  `

  logs.forEach((log) => {
    html += '<tr>'
    html += `<td>${formatDateTime(log.operationTime || log.createdAt || '')}</td>`
    html += `<td>${escapeHtml(log.ipAddress || '未知')}</td>`
    html += `<td>${escapeHtml(log.operatorName || log.operatorAccount || '匿名用户')}</td>`
    html += `<td>${escapeHtml(log.operatorRole || '未知')}</td>`
    html += `<td>${escapeHtml(log.module || '通用模块')}</td>`
    html += `<td>${escapeHtml(getOperationTypeLabel(log.operationType))}</td>`
    html += `<td>${escapeHtml(log.targetName || '--')}</td>`
    html += `<td>${escapeHtml(log.targetType || '未指定对象')}</td>`
    html += `<td>${log.resultStatus === 'success' ? '成功' : '失败'}</td>`
    html += `<td>${escapeHtml(getRiskLevelLabel(log.riskLevel))}</td>`
    html += `<td>${log.isRead ? '已读' : '未读'} / ${log.isAbnormal ? '异常' : '正常'}</td>`
    html += '</tr>'
  })

  html += `
        </tbody>
      </table>
    </body>
    </html>
  `

  return html
}

/**
 * HTML 转义
 */
function escapeHtml(text: string): string {
  const div = document.createElement('div')
  div.textContent = text
  return div.innerHTML
}

/**
 * 获取操作类型标签
 */
function getOperationTypeLabel(operationType: string): string {
  const labels: Record<string, string> = {
    create: '新增',
    update: '修改',
    delete: '删除',
    review: '审核',
    export: '导出',
    import: '导入',
    config: '配置',
    login: '登录',
    visit_page: '访问页面',
    other: '其他',
  }
  return labels[operationType] || operationType
}

/**
 * 获取风险等级标签
 */
function getRiskLevelLabel(riskLevel?: string): string {
  if (!riskLevel) return '低风险'
  const labels: Record<string, string> = {
    low: '低风险',
    medium: '中风险',
    high: '高风险',
  }
  return labels[riskLevel] || '低风险'
}

/**
 * 格式化日期时间
 */
function formatDateTime(value: string): string {
  if (!value) return '--'
  try {
    const date = new Date(value)
    if (Number.isNaN(date.getTime())) return value
    return new Intl.DateTimeFormat('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    }).format(date)
  } catch {
    return value
  }
}

